#include "scoreshow.h"
#include "ui_scoreshow.h"
#include <QStringList>
#include <QDebug>
#include <QSqlRecord>
#include <QResizeEvent>
#include <QVector>
#include <QHeaderView>
#include <QListWidget>
#include <QCheckBox>
#include <QScrollBar>


// protected

bool ScoreShow::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress) {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        // 判断鼠标点击位置是否在listWidget范围内
        for (int i = 0; i < m_lwManager.size(); ++i)
        {
            if (!m_lwManager[i]->geometry().contains(mouseEvent->pos()))
            {
                // 如果不在范围内，隐藏listWidget
                m_lwManager[i]->hide();
            }
        }

    }
    // 其他事件默认处理
    return QWidget::eventFilter(obj, event);
}

void ScoreShow::changeEvent(QEvent * event)
{
    if(QEvent::WindowStateChange == event->type()){
        QWindowStateChangeEvent * stateEvent = dynamic_cast<QWindowStateChangeEvent*>(event);
        if(Q_NULLPTR != stateEvent){
            QScrollBar* scroll = ui->showTable->horizontalScrollBar();
            // 窗口最大的时候，记录滚动条的最大值
            if (this->isMaximized())
            {
                m_maxScrollOffset = scroll->maximum();
            }
            // 窗口从最大变到其他状态需要做的事情
            if(Qt::WindowMaximized == stateEvent->oldState()){
                qDebug() << "minmin";
                qDebug() << "new " << scroll->value() << scroll->maximum();
                qDebug() << "old " << m_curScrollOffset << m_maxScrollOffset;
                // 窗口没变之前（最大状态）滚动条就处于最大偏移量
                if (m_curScrollOffset == m_maxScrollOffset)
                {
                    // 缩小以后（当前）也要偏移量变最大（默认不会变最大）
                    scroll->setValue(scroll->maximum());
                    m_curScrollOffset = scroll->maximum();
                    qDebug() << "cur value" << scroll->value();
                }

            }
        }
    }

}


// public

ScoreShow::ScoreShow(DataController* dc, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ScoreShow),
    m_dc(dc)
{
    ui->setupUi(this);

    // 安装事件过滤器
    this->installEventFilter(this);
    ui->showTable->viewport()->installEventFilter(this);



    initConnection();
    m_curScrollOffset = 0;

    initShowTableUI();


}


void ScoreShow::resizeEvent(QResizeEvent *event)
{
    QSize size = event->size();
//    qDebug() << size.width() << size.height();
    ui->showTable->setGeometry(ui->showTable->x(), ui->showTable->y(), size.width()-290, size.height()-20);
    ui->showItemBox->setGeometry(ui->showItemBox->x(), ui->showItemBox->y(), ui->showItemBox->width(), size.height()-170);
    refreshVisibleLW();
//    QScrollBar* scroll = ui->showTable->horizontalScrollBar();
//    maxScrollOffset = scroll->maximum();
//    qDebug() << "maxScroll become " << maxScrollOffset;
}

ScoreShow::~ScoreShow()
{

    delete ui;
}

// slot

void ScoreShow::onChosenColoumSelect(const QString chosenColumn)
{
    qDebug() << chosenColumn;
    // 避免内存泄露
    while(ui->showItemBox->count() > 0) {
//        delete ui->showItemBox->item(0); // 释放对应项的内存
        ui->showItemBox->takeItem(0); // 从控件中移除该项
    }
    qDebug() << "发送更新左边listwidget信号";
    emit chooseNewField(chosenColumn);

}


void ScoreShow::addItemUi(const QVector<QString> itemName)
{
    for (int i = 0; i < itemName.size(); ++i)
    {
        ui->showItemBox->addItem(itemName[i]);
//        QListWidgetItem *item = new QListWidgetItem;
        //    item->setSizeHint(QSize(10, 100));
//        ui->showItemBox->addItem(item);
//        QCheckBox* cb = new QCheckBox(itemName[i]);
//        connect(cb, SIGNAL(clicked()), this, SLOT(renewTable()));
//        ui->showItemBox->setItemWidget(item, cb);
    }
    qDebug() << "左边listwidget更新成功";
}

void ScoreShow::initShowTable(const QStringList fields)
{
    //填充左侧cobobox
    ui->chooseColumn->addItems(fields);
    // 初始不显示内容
//    ui->chooseColumn->setCurrentIndex(-1);

    // 设置表格列数
    ui->showTable->setColumnCount(fields.size());
    // 设置表格列字段
    ui->showTable->setHorizontalHeaderLabels(fields);

}

void ScoreShow::initTableInfo(const QVector<QVector<QString>> info)
{
    // 设置表格行数
    ui->showTable->setRowCount(info.size());
    // 填充每一行内容
    for (int i = 0; i < info.size(); ++i)
    {
        for (int j = 0; j < info[i].size(); ++j)
        {
            ui->showTable->setItem(i, j, new QTableWidgetItem(info[i][j]));
            ui->showTable->item(i, j)->setTextAlignment(Qt::AlignCenter);
        }
    }
    qDebug() << "初始化表格内容成功";
    initListWidgets();

}


void ScoreShow::onColumnWidthChanged(int logicalIndex, int oldSize, int newSize)
{
    refreshVisibleLW();
}

void ScoreShow::onHeaderClicked(int logicalIndex)
{
    if (!m_visibleLWMap[logicalIndex])
    {
        qDebug() << logicalIndex << "未全显示不可见";
        return;
    }
    QListWidget* lw = m_lwManager[logicalIndex];
    QHeaderView * columnHeader = ui->showTable->horizontalHeader();
    // 初始为左边那列标号的宽度
    int curOffset = ui->showTable->verticalHeader()->width();
    // 如果表没有横向滚动条，就不用计算滚动条的偏移
    if (!ui->showTable->horizontalScrollBar()->isVisible())
    {
        for (int i = 0; i < logicalIndex; ++i)
        {
            curOffset += ui->showTable->columnWidth(i);
        }
    }
    else
    {

        int scrollOffset = ui->showTable->horizontalScrollBar()->value();
        qDebug() << ui->showTable->verticalScrollBar()->width();
        // 特殊情况，滚轮偏移量处于最大状态，位置从右累减计算
        if (scrollOffset == ui->showTable->horizontalScrollBar()->maximum())
        {
            int tableWidth = ui->showTable->width() - ui->showTable->verticalScrollBar()->width();
            for (int i = columnHeader->count()-1; i >= logicalIndex; --i)
            {
                tableWidth -= ui->showTable->columnWidth(i);
                curOffset = tableWidth;
            }
        }
        else    // 一般情况，滚轮偏移量不是最大，位置从左累加计算
        {
            for (int i = scrollOffset; i < logicalIndex; ++i)
            {
                curOffset += ui->showTable->columnWidth(i);
            }
        }
    }

    lw->setGeometry(curOffset, columnHeader->height(), columnHeader->sectionSize(logicalIndex), m_lwManager[logicalIndex]->height());
    if (lw->isVisible())
    {
        lw->hide();
        qDebug() << "隐藏";
    }
    else
    {
        lw->show();
        qDebug() << "显示";
    }

}

// private

void ScoreShow::initConnection()
{
    // 信号组：主线程ui信号，主线程请求子线程信号，子线程返回主线程信号

    // ps:为什么组件发出信号不能直接给dc处理？
    // 组件发出信号后，需要主线程更新UI，清除listwidget中本来的东西，子线程无法实现

    // 组件发出信号，主线程接受处理
    connect(ui->chooseColumn, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(onChosenColoumSelect(const QString &)));
    // 当选择不同属性时，主线程请求子线程获取listwidget的每一项
    connect(this, &ScoreShow::chooseNewField, m_dc, &DataController::renewListItem);
    // 子线程传回数据给主线程，主线程更新组件UI
    connect(m_dc, &DataController::addItemToListView, this, &ScoreShow::addItemUi);

    // 主线程向子线程请求所有字段
    connect(this, &ScoreShow::getAllField, m_dc, &DataController::getAllFieldFromDB);
    // 子线程返回所有字段给主线程
    connect(m_dc, &DataController::returnAllFields, this, &ScoreShow::initShowTable);


    // 主线程向子线程请求所有记录
    connect(this, &ScoreShow::getAllInfo, m_dc, &DataController::getAllInfoFromDB);
    // 子线程返回所有记录给主线程
    connect(m_dc, &DataController::returnAllInfo, this, &ScoreShow::initTableInfo);

    // 请求子线程获取每个字段的内容
    connect(this, &ScoreShow::getFieldInfo, m_dc, &DataController::getFieldInfoFromDB);
    // 子线程返回字段内容，填充每一列的listwidget
    connect(m_dc, &DataController::returnFieldInfo, this, &ScoreShow::fillListWidgets);

    // 筛选条件改变，请求子线程查询新的内容
    connect(this, &ScoreShow::getFieldInfoWithCondition, m_dc, &DataController::getFieldInfosFromDB);
    // 子线程传回要显示在qtablewidget中的内容
    connect(m_dc, &DataController::returnNewTableShowInfo, this, &ScoreShow::refreshTableInfo);

    // 连接列宽变化信号
    connect(ui->showTable->horizontalHeader(), &QHeaderView::sectionResized, this, &ScoreShow::onColumnWidthChanged);
    // 连接水平头点击信号
    connect(ui->showTable->horizontalHeader(), &QHeaderView::sectionClicked, this, &ScoreShow::onHeaderClicked);
    // 连接水平滚动条发生变化信号
    connect(ui->showTable->horizontalScrollBar(), &QScrollBar::valueChanged, this, [=](int offset){
        qDebug() << offset;
        m_curScrollOffset = ui->showTable->horizontalScrollBar()->value();
        refreshVisibleLW();
    });
}

void ScoreShow::initShowTableUI()
{

    // 设置表格不可编辑
    ui->showTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
    // 设置行高固定
    ui->showTable->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    // 设置每个元素居中
    ui->showTable->setSelectionBehavior(QAbstractItemView::SelectRows);

    qDebug() << "发出请求所有字段信号（填充表头和左边下拉框）";
    emit getAllField();
    qDebug() << "发出请求所有记录信号（初始化表格内容）";
    emit getAllInfo();

}

void ScoreShow::initListWidgets()
{
    // 获取水平表头视图
    QHeaderView *columnHeader = ui->showTable->horizontalHeader();
    int rowHeaderOffset = ui->showTable->verticalHeader()->width();

//    qDebug() << "cur header width" << rowHeaderOffset;
    QVector<QString> fieldList;
    for (int i = 0; i < columnHeader->count(); ++i)
    {
        fieldList.append(ui->showTable->horizontalHeaderItem(i)->text());
        QListWidget * lw = new QListWidget(ui->showTable);
        m_lwManager.append(lw);

        lw->setGeometry(columnHeader->sectionPosition(i)+rowHeaderOffset, columnHeader->height(), columnHeader->sectionSize(0), 200); // 设置窗口的大小和位置
        //        lw->show();
//        qDebug() << ui->showTable->verticalHeader()->width();
    }
    qDebug() << "发出请求信号listwidget内容信号";
    emit getFieldInfo(fieldList);
}



// 把收到的数据显示到table中
void ScoreShow::refreshTableInfo(const QVector<QVector<QString>> infos)
{
//    ui->showTable->clear();
    ui->showTable->setRowCount(infos.size());
    qDebug() << infos.size();
    for (int i = 0; i < infos.size(); ++i)
    {
        for (int fieldIndex = 0; fieldIndex < infos[i].count(); ++fieldIndex)
        {
//            QTableWidgetItem * item = ui->showTable->item(i, fieldIndex);
//            delete item;
            ui->showTable->setItem(i, fieldIndex, new QTableWidgetItem(infos[i][fieldIndex]));
            ui->showTable->item(i, fieldIndex)->setTextAlignment(Qt::AlignCenter);

        }
    }
    refreshVisibleLW();
    qDebug() << "刷新表格内容完毕";
}

// 填充每列的listwidget，并且连接checkbox的信号
void ScoreShow::fillListWidgets(const QVector<QVector<QString>> infos)
{
    for (int fieldIndex = 0; fieldIndex < infos.size(); ++fieldIndex)
    {
        QListWidget* lw = m_lwManager[fieldIndex];
        for (int i = 0; i < infos[fieldIndex].size(); ++i)
        {
            QListWidgetItem *item = new QListWidgetItem(lw);
            //    item->setSizeHint(QSize(10, 100));
            lw->addItem(item);
            QCheckBox* cb = new QCheckBox(infos[fieldIndex][i], this);
//            connect(cb, SIGNAL(clicked()), this, SLOT(renewTable()));
            connect(cb, &QCheckBox::stateChanged, this, &ScoreShow::refreshConditions);
            lw->setItemWidget(item, cb);
        }
    }
    qDebug() << "所有列listwidget填充完毕";
    refreshVisibleLW();
}

// 更新筛选条件，重新请求数据
void ScoreShow::refreshConditions(int state)
{
    QVector<QString> fieldList;
    QVector<QVector<QString>> conditionList;
    for (int lwIndex = 0; lwIndex < m_lwManager.size(); ++lwIndex)
    {
        fieldList.append(ui->showTable->horizontalHeaderItem(lwIndex)->text());
        QListWidget* lw = m_lwManager[lwIndex];
        QVector<QString> condition;
        for (int cbIndex = 0; cbIndex < lw->count(); ++cbIndex)
        {
            QCheckBox* cb = qobject_cast<QCheckBox*>(lw->itemWidget(lw->item(cbIndex)));
            if (cb->isChecked())
            {
                condition.append(cb->text());
            }
        }
        conditionList.append(condition);
    }
    qDebug() << "发出更改表格内容信号";
    emit getFieldInfoWithCondition(fieldList, conditionList);
}

void ScoreShow::refreshVisibleLW()
{
    qDebug() << "刷新可见列表";
    // 刷新列表前先隐藏全部
    for (int i = 0; i < m_lwManager.size(); ++i)
    {
        m_lwManager[i]->hide();
    }
    // 如果表没有横向滚动条，就不用计算，全部可见
    if (!ui->showTable->horizontalScrollBar()->isVisible())
    {
        qDebug() << "没有滚动条，不用费事儿算滚轮";
        for (int i = 0; i < m_visibleLWMap.size(); ++i)
        {
            m_visibleLWMap[i] = true;
        }
        return;
    }
    QHeaderView *columnHeader = ui->showTable->horizontalHeader();
    QScrollBar* horizontalScrollBar = ui->showTable->horizontalScrollBar();
    int scrollOffset = horizontalScrollBar->value();
    int rowHeaderOffset = ui->showTable->verticalHeader()->width();
    int tableWidth = ui->showTable->width();
    int tableViewWidth = ui->showTable->viewport()->width();
    qDebug() << tableWidth << tableViewWidth;
    int curlen = rowHeaderOffset;
    // 先全设为隐藏的
    for (int i = 0; i < m_visibleLWMap.size(); ++i)
    {
        m_visibleLWMap[i] = false;
    }
    // 小于这个偏移量的一定是隐藏的，大于这个偏移量不一定是出现的
    qDebug() << "开始检测，滚轮偏移：" << scrollOffset;

    for (int i = scrollOffset; i < columnHeader->count(); ++i)
    {
        //        qDebug() << "第" << i+1 << "列累加长度：" << curlen;
        curlen += ui->showTable->columnWidth(i);
        //        qDebug() << "第" << i+1 << "列累加长度：" << curlen;
        if (curlen > tableWidth)
        {
            break;
        }
        m_visibleLWMap[i] = true;
        //        qDebug() << "不隐藏";
    }
}

// 测试按钮
void ScoreShow::on_testBtn_clicked()
{
    refreshVisibleLW();
    QHeaderView *columnHeader = ui->showTable->horizontalHeader();
    qDebug() << "全显示内容：";
    for (int i = 0; i < columnHeader->count(); ++i)
    {
        if (m_visibleLWMap[i])
        {
            qDebug() << ui->showTable->horizontalHeaderItem(i)->text();
        }
    }
}


void ScoreShow::on_clearAllBtn_clicked()
{
    for (int lwIndex = 0; lwIndex < m_lwManager.size(); ++lwIndex)
    {
        QListWidget* lw = m_lwManager[lwIndex];
        for (int cbIndex = 0; cbIndex < lw->count(); ++cbIndex)
        {
            QCheckBox* cb = qobject_cast<QCheckBox*>(lw->itemWidget(lw->item(cbIndex)));
            cb->setChecked(false);
        }
    }
}


void ScoreShow::on_backBtn_clicked()
{
    ui->showTable->clear();
    ui->showTable->setRowCount(0);
    ui->showTable->setColumnCount(0);
    ui->showItemBox->clear();
    ui->chooseColumn->clear();
    this->hide();
    emit showHomePage();
}

